package simplex

/**
 * Tipo racional con las operaciones comunes.
 * 
 * Codigo extraido de:
 * http://www.ibm.com/developerworks/java/library/j-scala02198/index.html
 * Al que le hemos añadido mas cosas
 * 
 * @author age, joaquinmonleon
 *
 */
class Racional(n:Int, d:Int)
{  
  private def gcd(x:Int, y:Int): Int =
  {
    if (x==0) y
    else if (x<0) gcd(-x, y)
    else if (y<0) -gcd(x, -y)
    else gcd(y%x, x)
  }
  
  private val g = gcd(n,d)
  
  val numer:Int = n/g
  val denom:Int = d/g
  
  implicit def +(that:Racional):Racional =
    new Racional(numer*that.denom + that.numer*denom, denom * that.denom)
  implicit def -(that:Racional):Racional =
    new Racional(numer * that.denom - that.numer * denom, denom * that.denom)
  implicit def *(that:Racional):Racional =
    new Racional(numer * that.numer, denom * that.denom)
  implicit def /(that:Racional):Racional =
    new Racional(numer * that.denom, denom * that.numer)

  implicit def >=(that:Racional):Boolean =
    return numer*that.denom >= that.numer*denom;
  implicit def <=(that:Racional):Boolean =
    return numer*that.denom <= that.numer*denom;
  implicit def >(that:Racional):Boolean =
    return numer*that.denom > that.numer*denom;
  implicit def <(that:Racional):Boolean =
    return numer*that.denom < that.numer*denom;
  
  override def toString() = {
    if (numer == 0)
      "0"
    else if (denom == 1)
      numer + ""
    else
      "[" + numer + " / " + denom + "]"
  }
    
  def unary_- : Racional = 
    return new Racional(-numer,denom);
}

object Racional{
	private def numeroDeDecimales(numero : Double): Int = {
		   var encontrado:Boolean = false;
		   var decimales:Int = 0;
		   var cadena:String = numero.toString();
		   var it:Iterator[Char] = cadena.reverseIterator;
		   while(it.hasNext){
		     var numero:Char = it.next();
		     if(numero=='0' && encontrado==false)
	       return decimales;
	     else if(numero=='.')
			       return decimales;
			     decimales+=1;
			     encontrado = true;
			   }
			   return decimales;
	}

	private def mypow(n : Int):Int = {
	  var retorno:Int = 10;
	  for (i <- 1 until n)
	    retorno*=retorno;
	  return retorno;
	}
	
	implicit def double2Racional(x:Double):Racional = {
		if(x==0.0)
		  return new Racional(0,1);
		
		var numerador:Int = 3;
		var denominador:Int = 3;
		
		var numDec:Int = numeroDeDecimales(x);
		
		//println( numDec );
		
		denominador = mypow(numDec);
		numerador = (x*denominador.doubleValue()).intValue();
		return new Racional(numerador,denominador);
	}
	
	implicit def int2Racional(x:Int):Racional = {
		if(x==0)
		  return new Racional(0,1);
		return new Racional(x,1);
	}
	
}

